#pragma once

#include <MyFC/Container.h>
#include <MyFC/Event.h>

#include "Segment.h"
#include "DLL.h"

#include <list>
#include <vector>

namespace My {

class Timeline;
class SegmentList;
class SegmentControl;

typedef std::list<SegmentControl *>		SegmentControlList;
typedef SegmentControlList::iterator	SegmentControlIndex;
typedef std::vector<SegmentControl *>	SegmentControlVector;

class DLL_API SegmentControl : public Container  
{
	class Control : public My::Control
	{
	protected:
		SegmentControl &	m_Control;
		SegmentList &		m_List;
		Timeline &			m_Timeline;
	public:
		Control(SegmentControl & s) 
			: m_Control(s), m_List(s.m_List), m_Timeline(s.m_Timeline)
		{
			m_Control.Add(this);
		}
	};

	class LeftBracket : public Control
	{
	private:
		int		m_StartPos;
		int		m_StartValue;
	public:
		LeftBracket(SegmentControl & s) : Control(s) { }
	public:
		virtual CRect Bounds() const;
		virtual String Hint() const 
			{ return "Segment Back End"; }
		virtual void HandleLeftDown(unsigned int flags, const CPoint & p);
		virtual bool HandleDragStart(unsigned int flags, const CPoint & p0, const CPoint & p);
		virtual void HandleDragEnd(unsigned int flags, const CPoint & p);
		virtual void HandleDragging(unsigned int flags, const CPoint & p);
	};

	class RightBracket : public Control
	{
	private:
		int		m_StartPos;
		int		m_StartValue;
	public:
		RightBracket(SegmentControl & s) : Control(s) { }
	public:
		virtual CRect Bounds() const;
		virtual String Hint() const 
			{ return "Segment Front End"; }
		virtual void HandleLeftDown(unsigned int flags, const CPoint & p);
		virtual bool HandleDragStart(unsigned int flags, const CPoint & p0, const CPoint & p);
		virtual void HandleDragEnd(unsigned int flags, const CPoint & p);
		virtual void HandleDragging(unsigned int flags, const CPoint & p);
	};

private:
	Timeline &			m_Timeline;
	SegmentList &		m_List;
	int					m_Index;
	Segment *			m_pSegment;
	LeftBracket			m_LeftBracket;
	RightBracket		m_RightBracket;
	SegmentControlIndex	m_AnimatedIndex;
	CPoint				m_BrushOrg;
	Span				m_TimeSpan;
private:
	Segment & GetSegment() const;
	Span GetTimeSpan() const;
	void SetTimeSpan(Span s);
	void UpdateTimeSpan();
	int GetOrigin() const;
	CRect GetUnionSpanRect() const;
public:
	virtual CRect Bounds() const;
	virtual String Hint() const;
public:
	SegmentControl(SegmentList &);
	~SegmentControl();
public:
	bool IsEmpty() const;
	void SetSegmentIndex(int index);
	void StartAnimation();
	void StopAnimation();
	void Animate();
protected:
	virtual void ProcessEvent(My::Event &);
	virtual void Paint(CDC * pDC, const CRect & r);
	virtual void HandleKeyDown(unsigned int key, unsigned int count, unsigned int flags);
	virtual void HandleLeftDown(unsigned int flags, const CPoint & p);
	virtual void HandleLeftDoubleClick(unsigned int flags, const CPoint &p);
	virtual bool HandleDragStart(unsigned int flags, const CPoint & p0, const CPoint & p);
	virtual void HandleDragEnd(unsigned int flags, const CPoint & p);
	virtual void HandleDragging(unsigned int flags, const CPoint & p);
	virtual void HandleFocus();
	virtual void HandleUnfocus();
public:
	virtual void OnInitialUpdate();
	virtual void OnTimeSpanChanged();
	virtual void OnDataSpanChanged();
	virtual void OnStatusChanged();
};

} // My
